package org.example.learn.bytebuddy.monitor;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;

import java.lang.reflect.InvocationTargetException;

// 使用byte-buddy 生成类并委托Monitor类的方法进行监控
public class GenerateClass {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        // DynamicType 动态类型,所有字节操作的开始
        //      Unloaded 动态创建的字节码还未加载进入虚拟机，需要类加载器进行加载
        //      Loaded 已加载到虚拟机(JVM)中，解析出的Class
        //      Default DynamicType的默认实现，完成相关实际操作
        // ByteBuddy 流式API的入口类
        //      提供Subclassing/Redefining/Rebasing方式改写字节码
        //      所有操作依赖于DynamicType.Builder进行，创建不可变对象
        DynamicType.Unloaded<?> dynamicType = new ByteBuddy()
                // 指定继承的父类 Goal
                .subclass(Goal.class)
                // 覆盖父类的方法：goalMethod
                // ElementMatchers 提供一系列的元素匹配工具类（named、any、nameEndsWith等等）
                //      ElementMatcher 提供对类型、方法、字段、注解进行matches的方式，类似于Predicate
                //      Junction 对多个ElementMatcher进行and或or操作
                .method(ElementMatchers.named("goalMethod"))
                // 拦截 并将goalMethod方法委托给Monitor
                // Implementation 提供动态方法的实现
                //      FixedValue 方法调用返回固定值
                //      MethodDelegation 方法调用委托: 支持Class的static方法调用; Object的instance method方法调用
                .intercept(MethodDelegation.to(Monitor.class))
                .make();
        // 利用Java反射 执行该方法
        Class<?> clazz = dynamicType.load(GenerateClass.class.getClassLoader()).getLoaded();
        Object val = clazz.getMethod("goalMethod",String.class,int.class).invoke(clazz.newInstance(),"zhangshan",1001);
//        System.out.println("结果: " + val);
    }
}
